<?php

define('COMPANY_LICENSE_BASEDIR', JPATH_ROOT."/images/jobs/company");
JLoader::register("Upload", JPATH_SITE.'/components/com_easygallery/class.upload.php/class.upload.php');

JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_puser/tables');
JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_jobs/tables');

/**
 * Registration controller class for Users.
 */
class PCompanyModelCompany extends JModelLegacy
{
   public function getTable($name='', $prefix='PUserTable', $options = array()) {
      return JTable::getInstance($name, $prefix);
   }

   protected function loadUser($userid) {
      $db = PFactory::getDbo();

      $query = 'SELECT c.*, u.* ' .
        ' FROM #__users AS u' .
        ' LEFT JOIN #__comprofiler AS c ON c.user_id=u.id ' .
        ' WHERE u.block=0 AND u.id=' . intval($userid);
      $db->setQuery($query);
      return $db->loadObject();
   }

   protected function validateFields($fields=array()) {
      foreach($fields as $field => $value) {
        switch($field) {
          case 'name':
             if(strlen($value) < 2) {
                $this->setError("请输入一个长度最少是 2 的字符串");
                return false;
             }
          break;
          case 'email':
             if(!JMailHelper::isEmailAddress($value)) {
                $this->setError("请输入正确格式的电子邮件");
                return false;
             }
          break;

          case 'password':
             if(!preg_match("/^[^\s]{6,255}$/i", $value)) {
                $this->setError("请输入有效的密码，至少6个字符，可包含数字、字母或其他字符，不允许使用空格");
                return false;
             }
          break;

          case 'phone':
             if(strlen($value) > 0 && !JobHelper::isPhone($value)) {
                $this->setError("请输入正确的联系电话");
                return false;
             }
          break;
        }

      }

      return true;
   }

   public function checkUniqueCompanyName($name) {
      $db = PFactory::getDbo();
      $user = PFactory::getMasterUser();

      /*FIXME: here we can only check prefix same company names. */
      $query = 'SELECT COUNT(*) ' .
        ' FROM #__users' .
        ' WHERE block=0 ' . ($user->id > 0 ? ' AND id != ' . $user->id : '') .
        ' AND name LIKE ' . $db->quote($name. '%');

      $db->setQuery($query);
      return $db->loadResult() <= 0;
   }

   public function checkUniqueSubDomain($sub_domain) {
      $db = PFactory::getDbo();

      $user = PFactory::getUser();
      $query = 'SELECT COUNT(*) ' .
        ' FROM #__jobs_employer' .
        ' WHERE ' . ($user->id > 0 ? ' user_id != ' . $user->id : '') .
        ' AND sub_domain = ' . $db->quote($sub_domain);

      $db->setQuery($query);
      return $db->loadResult() <= 0;
   }

   /**
    * Function getCompanyId
    * @param  string $sub_domain Company subdomain
    * @param  int    $company_id Company id
    * @return int                Company id
    */
   public function getCompanyId($sub_domain) {
      $db = PFactory::getDbo();
      if (empty($sub_domain))
        return 0;

      $query = "SELECT user_id FROM #__jobs_employer
        WHERE sub_domain = " . $db->quote($sub_domain) . " LIMIT 1";
      $db->setQuery($query);
      $user_id = $db->loadResult();

      // If empty set, and sub_domain looks like an user id, we can drag it out
      if (empty($user_id) && preg_match("/^[0-9]+$/", $sub_domain)) {
        $query = "SELECT user_id FROM #__jobs_employer
          WHERE user_id = " . $db->quote($sub_domain) . " LIMIT 1";
        $db->setQuery($query);
        $user_id = $db->loadResult();
        // Still null? return 0...
        return $user_id ? $user_id : 0;
      }
      return $user_id ? $user_id : 0;
   }
   
   /**
    * Method to check no used subaccount.
    */
   public function isDesertedUser($uid) {
      $db = PFactory::getDbo();
      $query = "SELECT COUNT(*) FROM *PREFIX*users_extended AS ue " .
             " LEFT JOIN *PREFIX*users AS u ON u.uid=ue.uid" .
             " WHERE (ue.block=1 OR ue.deleted=1) AND u.uid = " . $db->quote($uid);
      $db->setQuery(PUtil::replaceOCPrefix($query));
      return $db->loadResult() > 0 ? true : false;
   }

   /**
    * Method to log in a user.
    */
   public function login() {
      /* disable token for login form to avoid session time out - we have captcha for security protection 
      if(!PSession::checkToken('post')) {
        $this->setError('非法的系统安全码');
        return false;
      }
      */
      $app = PFactory::getApplication();

      /* captch is enforced. Before sending email, check captch. We have put it here as any success check will invalidate current code */
      if(!isDevMode()) {
        $needcaptcha = $app->getUserState("login_failed_captcha", false);
        if($needcaptcha) {
          $securimage = new Securimage();
          if($securimage->check(JRequest::getString("captcha_code", '')) == false) {
             jexit(jsonError("输入的安全码与图片显示不符,请重新输入<captcha_code></captcha_code>"));
          }
        }
      }
      
      $username = JRequest::getString("username", "");
      $password = JRequest::getString("password", "");
      
      if($this->isDesertedUser($username)) {
        $this->setError('该账号已被停用或注销');
        return false;
      }

      /* perform form login directly; the remember login is controlled by handleRequest */
      $this->directLogin($username, $password);

      if(!OC_User::isLoggedIn()) {
        $this->setError('用户名和密码不匹配');
        return false;
      }

      $db = PFactory::getDbo(); 
      // stay on master: read-your-write 
      $db->stayOnMaster(); 

      $user = PFactory::getUser();
      // user chould be not valid as if the logged user is sub-user of the company user
      if(!$user->get("guest")) {
         if($user->get("id") > 0) {
            JobHelper::setLastLogonDate($user);
            // Event Driven Cache/Object Caching - clear any cache related to affected tables 
            CacheHelper::triggerRemove($user->id, array('#__comprofiler'));
         }
         else {
            PCompanyHelper::setSubUserLastLogonDate($user->get("username"));
            CacheHelper::triggerRemove($user->get('owner'), array('*PREFIX*users_extended'));
         }
      }

      // leave on master enforcement now 
      $db->leaveOnMaster(); 

      return true;
   }

   public function directLogin($email, $password) {
      if (empty($email) || empty($password)) {
        return false;
      }

      $post = JRequest::get("post");
      OC_App::loadApps();

      //setup extra user backends
      OC_User::setupBackends();

      if (OC_User::login($email, $password)) {
        // setting up the time zone
        if (isset($post['timezone-offset'])) {
          $_SESSION['timezone'] = $post['timezone-offset'];
        }

        if (!empty($post["remember_login"])) {
          if (defined("DEBUG") && DEBUG) {
             OC_Log::write('core', 'Setting remember login to cookie', OC_Log::DEBUG);
          }

          // Create the encryption key, apply extra hardening using the user agent string.
          $privateKey = PApplication::getHash(@$_SERVER['HTTP_USER_AGENT']);

          $key = new JCryptKey('simple', $privateKey, $privateKey);
          $crypt = new JCrypt(new JCryptCipherSimple, $key);
          $credentials = array('username'=>$email, 'password'=>$password);
          $rcookie = $crypt->encrypt(serialize($credentials));
          $lifetime = time() + 365 * 24 * 60 * 60;

          // Use domain and path set in config for cookie if it exists.
          $cookie_domain = PFactory::getConfig()->get('cookie_domain', '');
          $cookie_path = PFactory::getConfig()->get('cookie_path', '/');
          setcookie(PApplication::getHash('PLOGIN_REMEMBER'), $rcookie, $lifetime, $cookie_path, $cookie_domain);
        }
      }
      return true;
   }

   /**
    * Method to log out a user.
    *
    * @since   1.6
    */
   public function logout() {
      $cookie_domain = PFactory::getConfig()->get('cookie_domain', '');
      $cookie_path = PFactory::getConfig()->get('cookie_path', '/');
      setcookie(PApplication::getHash('PLOGIN_REMEMBER'), false, time() - 86400, $cookie_path, $cookie_domain);
      
      OC_User::logout();
      header("Location: " . OC::$WEBROOT . '/');
   }

   /**
    * Method to register into Joomla Platform
    *
    */
   private function _register($data) {
      $config = PFactory::getConfig();
      $db      = PFactory::getDbo();

      // Initialise the table with JUser.
      $user = new JUser;

      // Get the groups the user should be added to after registration.
      $data['groups'] = array();

      // Get the default new user group, Registered if not specified.
      $params  = JComponentHelper::getParams('com_users');
      $data['groups'][] = $params->get('new_usertype', 2);

      // Get usertype
      $query  = 'SELECT title AS name FROM #__usergroups WHERE id = ' . intval($params->get('new_usertype', 2));
      $db->setQuery($query);
      $data['usertype'] = $db->loadResult();

      // Bind the data.
      if (!$user->bind($data)) {
        $this->setError("绑定注册数据失败: " . $user->getError());
        return false;
      }

     // Store the data.
      if (!$user->save()) {
        $this->setError("保存注册数据失败: " . $user->getError());
        return false;
      }

      return $user;
   }

   /**
    * Method to register a user.
    *
    * @since   1.6
    */
   public function register() {
      /* disable token for register form to avoid session time out - we have captcha for security protection 
      // simple security check
      if(!PSession::checkToken()) {
        $this->setError('非法的系统安全码');
        return false;
      }
      */

      $db  =  PFactory::getDbo();
      $app =  PFactory::getApplication();

      $email = JRequest::getString("email", "");
      $password =  JRequest::getString("password", "");

      // Get the form data.
      $data   = JRequest::get('post');
      $data['name'] = trim($data['name']);
      $vcode = JRequest::getString("vcode", "");

      $config = PFactory::getConfig(); 
      if($config->get("deploytesting_mode", 0)) {
         if(strpos($email, "@pipapai.com") === FALSE) {
            $this->setError('<span class="text-warning">抱歉，云招聘服务正处于试运行状态，现在还不接受公司注册。如有兴趣，<a href="mailto:support@'.PUtil::serverDomain().'">请联系我们</a>。</span>');
            return false; 
         }
      }

      if(!isDevMode()) {
         /* captch is enforced. */
         $securimage = new Securimage();
         if($securimage->check(JRequest::getString("captcha_code", '')) == false) {
            $this->setError("输入的安全码与图片显示不符,请重新输入<captcha_code></captcha_code>");
            return false; 
         }
      }

      /* don't check vcode if it's local post, or in dev mode or is referred user */
      // if(!isDevMode() && !JobHelper::checkEmailVcode($vcode,$email)) {
      if(false) {
        $this->setError("错误的邮箱验证码");
        return false;
      }

      if(!isset($data['acceptedterms'])) {
         $this->setError("您必须接受服务条款才能注册");
         return false;
      }

      // validate each input field
      if(!$this->validateFields($data))
         return false;

      // stay on master for data completion 
      $db->stayOnMaster(); 
 
      $validmsg = JobHelper::validateEmail($email);
      if($validmsg !== true) {
         $db->leaveOnMaster(); 
         $this->setError($validmsg);
         return false;
      }
      
      if(OC_User::userExists($email)) {
         $db->leaveOnMaster(); 
         $this->setError("该邮箱地址已经注册");
         return false;
      }

      if(!$this->checkUniqueCompanyName($data['name'])) {
         $db->leaveOnMaster(); 
         $this->setError("该公司名称已被使用");
         return false;
      }

      //we need to record correct ip address based on async local request or direct register
      if(isLocalRequest() && isset($_POST['registeripaddr']))
        $data['registeripaddr']    =  $_POST['registeripaddr'];
      else
        $data['registeripaddr'] = getUserIp();

      $data['cb_usertype']          =  'employer';

      // pre-set username to be email
      $data['username'] = $email;

      // when we reach here, we are safe to create users. first register into Joomla platform
      $user = $this->_register($data);
      if($user === false) {
        $db->leaveOnMaster(); 
        return false;
      }

      // make sure the id is same with user_id too
      $data['id'] = $user->id;

      // okay. good to update comprofiler table
      $table = $this->getTable('Comprofiler');
      /* first trying to load existing entires, so later store can decide to insert or update */
      if(!$table->load($user->id)) {
        /* it's a new row. We need to populate the row first otherwise the key field won't be able to set */
        $table->user_id = $user->id;
        $table->id = $user->id;
        $table->getDbo()->insertObject($table->getTableName(), $table);
        /* alternatively, one can use _getList example in JModel to build row */
      }

      // save the changes
      if (!$table->save($data)) {
        $this->deleteUser($user);
        $this->setError($table->getError());
        $db->leaveOnMaster(); 
        return false;
      }

      $table->name = $user->name;
      // initiate other user related tables
      if(!$this->saveRegistration($table)) {
        $this->deleteUser($table);
        $db->leaveOnMaster(); 
        return false;
      }

      if(!$this->directLogin($email, $password)) {
        $this->deleteUser($table);
        $this->setError("系统错误，请稍后再试！");
        $db->leaveOnMaster(); 
        return false;
      }
     
      // leave on master enforcement now 
      $db->leaveOnMaster(); 

      // all below should create if doesn't exist when select later on 
      // automatically create calendar - should not wait to click interview management 
      OC_Hook::emit( "OC_User", "post_createMasterUser", array( "uid" => $user->id));
      
      // create default quota
      $query = "INSERT IGNORE INTO #__user_quota (user_id, type_id) SELECT " . intval($user->id) . " AS user_id, id FROM #__quota_types WHERE isfree=1";
      $db->setQuery($query);
      $db->execute();

      // create job saved folder
      $query = "INSERT IGNORE INTO *PREFIX*hr_job_folder (folder_name, owner, system) VALUES ('我的收藏', " . intval($user->id) . ", 1)";
      $db->setQuery(PUtil::replaceOCPrefix($query));
      $db->execute();
      
      // create resume saved folder
      $query = "INSERT IGNORE INTO *PREFIX*hr_resume_folder (folder_name, owner, system) VALUES ('我的收藏', " . intval($user->id) . ", 1)";
      $db->setQuery(PUtil::replaceOCPrefix($query));
      $db->execute();

      // success: update login activity for jobseeker login
      JobHelper::setLastLogonDate($user);
      $session  = PFactory::getSession();
      $session->set('first_register', true);;

      return $table;
   }

   /*
    * save register
    */
   public function saveRegistration($user) {
      $db = PFactory::getDbo();
      $row = JTable::getInstance('Employer', 'Table');
      $post = JRequest::get('post');
      $task = JRequest::getString("task");

      // Set default sub_domain
      //$post['sub_domain'] = $user->id;

      //yyjob: if it's individual, fill the contact name with user name
      if($user->cb_usertype == 'employer')
      {
        $post['comp_name'] = $user->name;

        if(isset($post['hire_type'])) {
          if($post['hire_type'] == 'I')
          {
             $post['contact_name'] = $post['comp_name'];
             $post['id_comp_type'] = '8'; // INDIVIDUAL
             $post['id_industry'] = '0';
          }
          else if($post['hire_type'] == 'H')
          {
             $post['id_comp_type'] = '9'; // HEADHUNTER
             $post['id_industry'] = '0';
          }
        }
      }

      /* first trying to load existing entires, so later store can decide to insert or update */
      $new = false; 
      if(!$row->load($user->id)) {
         $row->user_id = $user->id;
         $new = true; 
      }

      // Attempt to bind the source to the instance.
      if (!$row->bind($post)) {
         $this->setError($row->getError());
         return false;
      }

      // Run any sanity checks on the instance and verify that it is ready for storage.
      if (!$row->check()) {
         $this->setError($row->getError());
         return false;
      }

      $fields = array();
      $where = array();


      // Iterate over the object variables to build the query fields and values.
      // copy from update/insert object from database.php 
      foreach (get_object_vars($row) as $k => $v) {
         // Only process non-null scalars.
         if (is_array($v) or is_object($v) or $v === null) {
            continue;
         }

         // Ignore any internal fields.
         if ($k[0] == '_') {
            continue;
         }

         // Ignore vid or subdomain if it's new 
         if($new && ($k == 'vid' || $k == 'sub_domain')) {
            continue; 
         }
      
         // Prepare and sanitize the fields and values for the database query.
         $fields[] = $db->quoteName($k);
         $values[] = $db->quote($v);
      }

      if($new) {
            
         $fields[] = $db->quoteName('vid');
         $fields[] = $db->quoteName('sub_domain');
         $query = "INSERT INTO #__jobs_employer (" . implode($fields, ',') . ") " . 
                  " SELECT " . implode(',', $values) . ", 
                      (SELECT IF(mvid IS NULL, 500, IF(mvid>500, mvid,mvid+500)) FROM (SELECT max(vid)+1 AS mvid FROM #__jobs_employer) as b), 
                      (SELECT IF(mvid IS NULL, 500, IF(mvid>500, mvid,mvid+500)) FROM (SELECT max(vid)+1 AS mvid FROM #__jobs_employer) as b)";

         // Set the query and execute the insert.
         $db->setQuery($query);
         if (!$db->execute()) {
            $this->setError($db->getError());
            return false;
         }
      }
      else {
         if (!$row->store()) {
            $this->setError($row->getError());
            return false;
         }
      }

      // Update jos_comprofiler
      $query = "UPDATE #__comprofiler SET
        `address` = ".$db->quote($user->address).",
        `phone` = ".$db->quote($user->phone).",
        `city` = ".$db->quote($user->city).",
        `id_city` = ".intval($user->id_city).",
        `state` = ".$db->quote($user->state).",
        `id_state` = ".intval($user->id_state)."
        WHERE `id` =".$user->id;

      $db->setQuery($query);
      if (!$db->execute()) {
         return false;
      }
      
      // Event Driven Cache/Object Caching - clear any cache related to affected tables 
      CacheHelper::triggerRemove($user->id, array('#__jobs_employer'));

      return true;
   }

   function saveAccountSetting($user, $post) {
      $db      = PFactory::getDbo();
      $row     = JTable::getInstance('Employer', 'Table');

      $row->user_id = $user->id;

      if(!$row->load($user->id)) {
        $this->setError("公司不存在");
        return false;
      }

      $post = array_flatten($post);

      if (!$row->save($post)) {
        $this->setError($row->getError());
        return false;
      }

      return true;
   }

   function saveUserProfile($user, $post=null) {
      JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_jobs/tables');

      $db = PFactory::getDbo();
      $post   = $post ? $post : JRequest::get('post');

      $section = isset($post['section']) ? $post['section'] : JRequest::getString('section', '');

      switch($section) {
          case 'summary':
             if(isset($post['summary']))
                $post['summary'] = strmaxwordlen(JFilterOutput::cleanText($post['summary']), 2000);
             $row  = JTable::getInstance('Employer', 'Table');
             $keyfield = $user->id;
             if(!$row->load($keyfield)) {
                /* it's a new row. set user id field */
                $row->user_id = $user->id;
             }
          break;
      }

      if(!isset($row))
        return true;

      $post = array_flatten($post);
      if (!$row->save( $post )) {
        $this->setErrror($row->getError());
        return false;
      }

      // Event Driven Cache/Object Caching - clear any cache related to affected tables 
      CacheHelper::triggerRemove($user->id, array('#__jobs_employer'));

      return true;
   }

   private function deleteUser($user) {
      $table = JTable::getInstance('Employer', 'Table');
      $table->delete($user->id);

      $table = $this->getTable('Comprofiler');
      $table->delete($user->id);

      $user = PFactory::getUser($user->id);
      if($user)
        $user->delete();
   }

   function saveRegistrationData($userid=0) {
      // simple security check
      if(!PSession::checkToken()) {
        $this->setError('登录已失效，请重新登录');
        return false;
      }

      $userdata = $this->loadUser($userid);
      if(!$userdata) {
        // this should not happen
        $this->setError("公司不存在");
        return false;
      }

      // check permission if it's employer
      if($userdata->cb_usertype != 'employer') {
        $this->setError('您无权访问该资源');
        return false;
      }

      $user = new JObject();
      $user->setProperties($userdata);

      $task = JRequest::getString('task', '');
      $post = JRequest::get('post');

      if(!$this->validateFields($post))
        return false;

      $user->setProperties($post);

      if(!$this->saveRegistration($user))
        return false;

      return true;

   }

   function saveSettings() {
      // simple security check
      if(!PSession::checkToken()) {
        $this->setError('登录已失效，请重新登录');
        return false;
      }

      if(!PFactory::isMasterUser()) {
        $this->setError("您无权访问该资源");
        return false;
      }

      $me = PFactory::getMasterUser();
      $userid = JRequest::getInt("uid", 0);
      $userid = $userid ? $userid : $me->id;
      $isOwner = $me->id == $userid;
      $puser = $this->loadUser($userid);
      if(!$puser) {
        $this->setError("公司不存在");
        return false;
      }

      // check permission if it's employer
      if($puser->cb_usertype == 'employer') {
        // have to run getUser to get ACL information
        $company = PFactory::getUser($puser->id);

        $allow = (($isOwner && $company->authorise ("company.edit.own" , "com_company")) ||
               $me->authorise ( "company.edit" , "com_company" ));

        if(!$allow) {
          $this->setError(JText::_("JERROR_ALERTNOAUTHOR"));
          return false;
        }
      }
      else {
        $this->setError("您无权访问该资源");
        return false;
      }
      $post = JRequest::get('post');
      if(isset($post['comp_name'])) {
         $post['comp_name'] = trim($post['comp_name']);
      }
      if(JRequest::getString('contactnamefieldid')){
         UserPrivacy::getUserPrivacySettings($user, 'com_company');
            $result = UserPrivacy::setUserPrivacyValue($puser->id, JRequest::getString('contactnamefieldid'), 0, JRequest::getInt('contactnameprivacy'));
            if($result !== true){
               $this->setError($result);
               return false;
            }  
            $result = UserPrivacy::setUserPrivacyValue($puser->id, JRequest::getString('phonefieldid'), 0, JRequest::getInt('phoneprivacy'));
            if($result !== true){
               $this->setError($result);
               return false;
            }      
      } 	         
      // validate each input field
      if(!$this->validateFields($post))
        return false;

      // Sub-domain only have one chance to setup
      if ($puser->cb_usertype == "employer" && !empty($post['sub_domain'])) {
        if ($this->issetSubDomain()) {
          $this->setError("专属域名设置过后，不可更改。");
          return false;
        }
        $message = CensorHelper::validateSubDomain($post['sub_domain']);
        if($message != true) {
          $this->setError($message);
          return false;
        }
      }
      // Avoid OverWrite hack
      if (empty($post['sub_domain']))
        unset($post['sub_domain']);

      /* let's check whether this is passwd change */
      if(isset($post['currentpassword'])) {
        // validate current password
        $parts   = explode( ':', $puser->password );
        $crypt   = $parts[0];
        $salt = @$parts[1];
        $testcrypt = JUserHelper::getCryptedPassword($post['currentpassword'], $salt);

        if($crypt != $testcrypt) {
          $this->setError("当前密码错误");
          return false;
        }
        if(!$this->validateFields(array("password"=>JRequest::getString('newpassword', "", "post", JREQUEST_NOTRIM)))) {
           return false;
        }
        if($post['newpassword'] != $post['newpassword_verify']) {
          $this->setError("密码和验证密码不一致，请重试.");
          return false;
        }

        /* update password */
        $post['password'] = $post['newpassword'];
        $post['password2'] = $post['newpassword'];
      }

      /* company name might have been changed ? */
      if($puser->cb_usertype == 'employer' && !empty($post['comp_name'])) {
        $post['name'] = $post['comp_name'];
      }
      
      if (!empty($post['website'])) {
        $post['website'] = strpos($post['website'], '://') ? $post['website'] : "http://".$post['website'];
      }

      /* save users information */
      $user = PFactory::getUser($puser->id);
      // Bind the data.
      if (!$user->bind($post)) {
        $this->setError("绑定设置数据失败: " . $user->getError());
        return false;
      }

      // Store the data.
      if (!$user->save()) {
        $this->setError("保存数据失败: " . $user->getError());
        return false;
      }

      // update comprofiler tables
      $table = $this->getTable('Comprofiler');
      if(!$table->load($puser->id)) {
        // this will not happen
        $this->setError("公司不存在");
        return false;
      }

      $table->lastupdatedate =  PFactory::getDate()->toSql();
      // save the any changes belong to this table
      if (!$table->save($post)) {
        $this->deleteUser($user);
        $this->setError($table->getError());
        return false;
      }

      // update other setting data
      if(!$this->saveAccountSetting($puser, $post))
        return false;


      // If we reach here but not owner, it should be custome support
      if(!$isOwner) {
        SupportHelper::record("Update account setting for employer: ". $puser->name . ", ID: " . $puser->id);
      }

      // Event Driven Cache/Object Caching - clear any cache related to affected tables 
      CacheHelper::triggerRemove($user->id, array('#__jobs_employer'));

      return true;
   }

   public function saveProfile($save=true) {
      $me = PFactory::getMasterUser();

      $userid = JRequest::getInt("uid", 0);
      $userid = $userid ? $userid : $me->id;
      $isOwner = $me->id == $userid;

      $puser = $this->loadUser($userid);
      if(!$puser) {
        $this->setError('公司不存在');
        return false;
      }

      // check permission if it's employer
      if($puser->cb_usertype == 'employer') {
        // have to run getUser to get ACL information
        $company = PFactory::getUser($puser->id);

        $allow = (($isOwner && $company->authorise ("company.edit.own" , "com_company")) ||
                $me->authorise ( "company.edit" , "com_company" ));

        if(!$allow) {
          $this->setError('您无权访问该资源');
          return false;
        }
      }
      else {
        $this->setError("您无权访问该资源");
        return false;
      }

      if($save) {
        // save profile data
        if(!$this->saveUserProfile($puser)) {
          return false;
        }
      }

      // If we reach here but not owner, it should be custome support
      if(!$isOwner) {
        SupportHelper::record("Update profile for company: ". $puser->name . ", ID: " . $puser->id);
      }

      return true;
   }

   public function getProfileSummary($userid=0) {
      $query = "SELECT summary FROM #__jobs_employer WHERE user_id=" . intval($userid); 
    
      /* try to load from cache */
      $cache = CacheHelper::getCache('com_company');
      // get cached data now 
      $data = $cache->call(array($this, '_getProfileSummary'), $query);

      // Event Driven Cache/Object Caching
      // there are the tables which we need to invoke cache cleaning triggers when tables are changed by user - Event Driven Cache/Object Caching
      CacheHelper::setTriggers(intval($userid), $cache, array('#__jobs_employer'));
 
      return $data;
   }

   public function _getProfileSummary($query) {
      $db = PFactory::getDbo(); 
      $db->setQuery($query); 
      return $db->loadObject();
   }

   public function updateEmail() {
      $user = PFactory::getMasterUser();

      // simple spoof check security
      if(!PSession::checkToken()) {
        $this->setError('登录已失效，请重新登录');
        return false;
      }

      $puser = $this->loadUser($userid);
      if(!$puser) {
        $this->setError('公司不存在');
        return false;
      }

      // check permission if it's employer
      if($puser->cb_usertype != 'employer') {
        $this->setError('您无权访问该资源');
        return false;
      }


      $email = JRequest::getString("email", "");
      $vcode = JRequest::getString("vcode", "");

      /* check vcode again */
      if(!JobHelper::checkEmailVcode($vcode,$email)) {
        $this->setError("错误的邮箱验证码");
        return false;
      }

      /* normal user changing email */
      $oldmail = $user->email;
      $user->username = $email;
      $user->email  = $email;

      // check whether email is unique
      // Store the data.
      if (!$user->save()) {
        $user->username = $oldmail;
        $user->email  = $oldmail;
        $this->setError('该邮箱地址已经注册');
        return false;
      }

      // Event Driven Cache/Object Caching - clear any cache related to affected tables 
      CacheHelper::triggerRemove($user->id, array('#__users'));
      return true;
   }

   /* upload license */
   function uploadLicense()
   {
      $app = PFactory::getApplication();
      $user = PFactory::getMasterUser();

      $post   = JRequest::get('post');

      $upload =array(
              'tmp_name' => null,
              'name' => null,
              'size' => null,
              'type' => null,
              'error' => ""
      );

      if(empty($_FILES['Filedata'])) {
        return jsonError("没有上传数据", null, false);
      }

      $upload = array_merge($upload, $_FILES['Filedata']);

      // Check for security token
      if(!PSession::checkToken()) {
        $upload['error'] = '登录已失效，请重新登录';
        return json_encode($upload);
      }

      if($user->get("guest") || $user->get("id") <= 0) {
        $upload['error'] = '请先登录再上传营业执照';
        return json_encode($upload);
      }

      //UPLOAD FILE
      $allowTypes = array("application/msword",
                   "application/kswps",
                   "application/vnd.ms-office",
                   "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                   "message/rfc822",
                   "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                   "application/pdf",
                   "application/vnd.oasis.opendocument.text",
                   "application/vnd.oasis.opendocument.spreadsheet",
                   "image/jpeg",
                   "image/png",
                   );

      $target_path = JPath::clean(COMPANY_LICENSE_BASEDIR.'/'.$user->id);
      if(!JFolder::exists($target_path))
         JFolder::create($target_path);

      $filedata = $_FILES['Filedata'];
      $fileext = JFile::getExt($filedata['name']);
      $filedata['name'] = JApplication::stringURLSafe(JFile::stripExt($filedata['name'])) . "." . $fileext;
      $handle = new Upload($filedata, 'zh_CN');      
      if(!$handle) {
        $upload['error'] = $handle->error;
        return json_encode($upload);
      }
      //for some doc file which have html content
      if(($handle->file_src_mime == 'text/html' || $handle->file_src_mime == 'text/plain') && ($fileext == 'doc' || $fileext == 'docx' )){
         $handle->file_src_mime = 'application/msword';
         $handle->file_src_name_ext = $fileext;
      }
      $handle->allowed = $allowTypes;
      $handle->process($target_path);
      if (!$handle->processed) {
        $upload['error'] = $handle->error;
        return json_encode($upload);
      }

      // Initialize variables
      $db = PFactory::getDbo();
      $row = JTable::getInstance('Employer', 'Table');

      $row->load($user->id);
      // only file name
      $row->license_file = $handle->file_dst_name;
      $row->license_file_datetime = PFactory::getDate()->toSql();
      $row->validated = EMPLOYER_VALIDATING;
      // pre-save checks
      if (!$row->check()) {
        $upload['error'] = $row->getError();
        return json_encode($upload);
      }
      // save the changes
      if (!$row->store()) {
        $upload['error'] = $row->getError();
        return json_encode($upload);
      }

      $row->checkin();
      // Event Driven Cache/Object Caching - clear any cache related to affected tables 
      CacheHelper::triggerRemove($user->id, array('#__jobs_employer'));

      return json_encode($upload);
   }

   /* resume forwarding email */
   public function getResumeForwardEmail() {
      $user = PFactory::getMasterUser();

      $db = PFactory::getDbo();

      $query = "SELECT * FROM *PREFIX*hr_email WHERE company_id=" . $user->id;
      $db->setQuery(PUtil::replaceOCPrefix($query));

      $result = $db->loadAssoc();
      if($result && $result['email'])
        return $result;

      /* create the password */
      $password = JUserHelper::genRandomPassword(10);
      if(isDevMode() || isTestMode())
        $email = "testing.hr"; 
      else 
        $email = "";

      $query = "SELECT vid FROM  #__jobs_employer  WHERE user_id =" .$user->id;
      $db->setQuery($query);
      $vid = $db->loadResult();
      if(!$vid)
        return false;

      $email = $email . $vid . "@pipahr.com";
      $query = "INSERT INTO *PREFIX*hr_email (company_id, email, password) VALUES ( " .
              $user->id . ", " .
              $db->quote($email) . ", " .
              $db->quote($password) .
              ") ON DUPLICATE KEY UPDATE email=values(email), password=values(password)";

      $db->setQuery(PUtil::replaceOCPrefix($query));
      if(!$db->execute()) {
        return false;
      }

      /* call remote server to generate email user */
      exec("sudo /opt/pipahr/bin/genhremail.sh $email $password  > /dev/null &");

      return array('email'=>$email);
   }

   public function getStats() {
      $user = PFactory::getMasterUser();
      $db = PFactory::getDbo();
      /* the user must be valid */
      if(!$user || $user->id <= 0) {
        $this->setError('您无权访问该资源');
        return false;
      }
      
      $subSql = '';
      if(PCompanyHelper::isJobManager() && !PFactory::isMasterUser()) {
         $subuser = PCompanyHelper::getSubUser();
         if(!empty($subuser) && !empty($subuser->assignedjobs)) {
            $subSql .= ' AND jj.id IN (' . implode(',', $subuser->assignedjobs) . ') ';
         } else {
            $subSql .= ' AND jj.id = -1';
         }
      }

      /* try to load from cache */
      $cache = CacheHelper::getCache('app_company');
      
      /* get new total and new resumes */
      if (PFactory::isMasterUser() || PCompanyHelper::checkAdminAllPermission()) {
         $query = "SELECT num_jobseekers AS totalresumes FROM #__jobs_employer WHERE user_id=" . $user->id;
         // get cached data now 
         $resumes = $cache->call(array($this, '_getStats'), $query);
         CacheHelper::setTriggers($user->id, $cache, array('#__jobs_employer'));
      } else {
         $query = "SELECT count(*) AS totalresumes FROM *PREFIX*hr_jobseeker AS hj " .
                  " LEFT JOIN #__jobs_job AS jj ON jj.id=hj.job_id " .
                  " LEFT JOIN #__jobs_employer AS e ON e.user_id=jj.employer_id AND e.user_id=hj.company_id " .
                  " WHERE jj.is_trashed = 0 AND hj.is_trashed = 0 AND e.user_id = " . $user->id . $subSql;
         // get cached data now 
         $resumes = $cache->call(array($this, '_getStats'), $query);
         CacheHelper::setTriggers($user->id, $cache, array('*PREFIX*hr_jobseeker'));
      }
      
      

      /* get new job positions */
      $query = "SELECT " .
             " (SELECT count(*) FROM #__jobs_job WHERE is_trashed=0 AND system=0 AND publish_date>=e.cb_lastlogondate and employer_id=e.user_id) AS newjobs, ".
             " (SELECT count(*) FROM #__jobs_job AS jj WHERE jj.is_trashed=0 AND jj.system=0 AND jj.employer_id=e.user_id " . $subSql . ") AS totaljobs " .
             " FROM #__comprofiler AS e " .
             " WHERE e.user_id = " . $user->id;
      $jobs = $cache->call(array($this, '_getStats'), $query);

      // Event Driven Cache/Object Caching
      // there are the tables which we need to invoke cache cleaning triggers when tables are changed by user - Event Driven Cache/Object Caching
      CacheHelper::setTriggers($user->id, $cache, array('#__jobs_job'));

      return array('resumes'=>$resumes, 'jobs'=>$jobs);
   }

   public function _getStats($query) {
      $db = PFactory::getDbo();
      $db->setQuery(PUtil::replaceOCPrefix($query));

      return $db->loadAssoc();
   }

   /**
    * Function issetSubDomain
    * @return bool True[already setup], false[not yet]
    */
   public function issetSubDomain() {
      $user = PFactory::getUser();
      $db = PFactory::getDbo();
      /* the user must be valid */
      if(!$user || $user->id <= 0) {
        return true;
      }

      $query = "SELECT sub_domain
        FROM #__jobs_employer
        WHERE user_id=".intval($user->id);
      $db->setQuery($query);
      $sub_domain = $db->loadResult();

      if (preg_match("/^[0-9]+$/", $sub_domain) || empty($sub_domain) )
      {
        return false;
      }

      return true;
   }

   public function getLastResumes($isMasterUser){
      $user = OC_User::getUser();
      $db = PFactory::getDbo();
      /* the user must be valid */
      if(!$user) {
        $this->setError('您无权访问该资源');
        return false;
      }

      // below query to use ignore index to get rid of index_merge optimization which actually slows down the query 
      if($isMasterUser){
         $query = "SELECT count(*) AS totalresumes FROM *PREFIX*hr_jobseeker AS hj IGNORE INDEX (is_trashed)" .
                  " LEFT JOIN #__jobs_job AS jj ON jj.id=hj.job_id " .
                  " LEFT JOIN #__jobs_employer AS e ON e.user_id=jj.employer_id AND e.user_id=hj.company_id " .
                  " WHERE jj.is_trashed = 0 AND hj.is_trashed = 0 AND e.user_id = " . $user;
      }else{
         $subuser = PCompanyHelper::getSubUser();
         $query = "SELECT count(*) AS totalresumes FROM *PREFIX*hr_jobseeker AS hj IGNORE INDEX (is_trashed)" .
                  " LEFT JOIN #__jobs_job AS jj ON jj.id=hj.job_id " .
                  " LEFT JOIN #__jobs_employer AS e ON e.user_id=jj.employer_id AND e.user_id=hj.company_id " .
                  " LEFT JOIN *PREFIX*hr_jobmanager AS hjm on hjm.jobid = hj.job_id ".
                  " WHERE jj.is_trashed = 0 AND hj.is_trashed = 0 AND hjm.manager = '" . $subuser->uid ."'";
      }

      $totalresumes = array();
      $sqls = array();
      $sql_final = "";
      $aray_times = array('3d','1w','1m');
      foreach($aray_times as $time){
         list($starttime, $endtime) = PResumesHelper::getTimeRange($time);
         $startdate = PFactory::getDate($starttime)->format('Y-m-d H:i:s');
         $enddate = PFactory::getDate($endtime)->format('Y-m-d H:i:s');
         $searchSql = " AND hj.date_added >= ".$db->quote($startdate) ." AND hj.date_added < ".$db->quote($enddate);
         $sqls[$time] = $query.$searchSql;
      }
      foreach($sqls as $time=>$sql){
         $sql_final .= " (".$sql.") AS ".$time.", ";
      }
      $sql_final = "SELECT ".substr($sql_final,0,strlen($sql_final)-2);

      /* try to load from cache */
      $cache = CacheHelper::getCache('app_company');
      // get cached data now 
      $data = $cache->call(array($this, '_getLastResumes'), $sql_final);

      if($isMasterUser){
         CacheHelper::setTriggers(PFactory::getMasterUser()->get("id"), $cache, array('*PREFIX*hr_jobseeker', '#__jobs_job'));
      }else{
         CacheHelper::setTriggers(PFactory::getMasterUser()->get("id"), $cache, array('*PREFIX*hr_jobseeker', '#__jobs_job','*PREFIX*hr_jobmanager'));
      }
      
      return $data;
   }

   public function _getLastResumes($query) {
      $db = PFactory::getDbo();
      $db->setQuery(PUtil::replaceOCPrefix($query));
      $totalresumes = $db->loadAssoc(); 
      return count($totalresumes)>0 ? $totalresumes : false;
   }

   public function getLastInterview($isMasterUser){
      $userid = OC_USER::getUser();
      $db = PFactory::getDbo();
      $master_uid = PFactory::getMasterUser()->get("id");
      /* the user must be valid */
      if(!$userid) {
        $this->setError('您无权访问该资源');
        return false;
      }
      

      
      $totalinterview = array();
      $sqls = array();
      $sql_final = "";
      $aray_times = array('3d','1w','1m');
      foreach($aray_times as $time){
         list($starttime, $endtime) = PResumesHelper::getTimeRange($time);
         $startdate = PFactory::getDate($starttime)->format('Y-m-d H:i:s');
         $enddate = PFactory::getDate($endtime)->format('Y-m-d H:i:s');
         $searchSql = " AND ((b.enddate >= ".$db->quote($startdate) ." AND b.enddate < ".$db->quote($enddate).") OR (b.startdate >= ".$db->quote($startdate) ." AND b.startdate < ".$db->quote($enddate).") OR (b.startdate <= ".$db->quote($enddate)." AND b.repeating = 1)) AND IF(b.objecttype='VEVENT',od.result<>5,od.offer_stat<>2)";
         $sqls[$time] = "SELECT count(0) FROM (SELECT * FROM (
         SELECT DISTINCT b.*, ie.parent, ie.uid,od.result,od.offer_stat
         FROM *PREFIX*calendar_objects b
         LEFT JOIN *PREFIX*calendar_calendars c ON c.id = b.calendarid
         LEFT JOIN *PREFIX*calendar_interview_events ie ON ie.objectid = b.id
         LEFT JOIN *PREFIX*calendar_objects_details od ON od.objectid = ie.parent
         LEFT JOIN #__jobs_job jj ON jj.id = ie.jobid" .
         ( PFactory::isMasterUser() ? " LEFT JOIN *PREFIX*users_extended ux ON ux.uid = c.userid " : "" ) .
         ( PFactory::isMasterUser() ? "" : " LEFT JOIN *PREFIX*hr_jobmanager jm ON jm.jobid = od.jobid" ) .
         ( PFactory::isMasterUser() ? " WHERE jj.employer_id = ".intval($master_uid)." AND ie.parent = od.objectid AND " : " WHERE " ) .
         ( PFactory::isMasterUser() ? " ( c.userid = ".intval($userid)." OR ux.owner = ".intval($userid)." )" : " ( c.userid = ".$db->quote($userid)." OR jm.manager = ".$db->quote($userid).")" ) .$searchSql.
         " ORDER BY b.startdate ASC ) AS r ".
         ( PFactory::isMasterUser() ? " HAVING r.parent=r.id) AS SSS " : " GROUP BY r.parent HAVING r.parent=r.id OR (r.uid = ".$db->quote($userid)." AND r.parent <> r.id)) AS SSS " );
      }
      foreach($sqls as $time=>$sql){
         $sql_final .= " (".$sql." ) AS ".$time.", ";
      }
      $sql_final = "SELECT ".substr($sql_final,0,strlen($sql_final)-2);

      /* try to load from cache */
      $cache = CacheHelper::getCache('app_company');
      // get cached data now 
      $data = $cache->call(array($this, '_getLastInterview'), $sql_final);

      if($isMasterUser){
         CacheHelper::setTriggers(PFactory::getMasterUser()->get("id"), $cache, array('*PREFIX*calendar_objects_details', '*PREFIX*calendar_objects', '*PREFIX*calendar_calendars'));
      }else{
         CacheHelper::setTriggers(PFactory::getMasterUser()->get("id"), $cache, array('*PREFIX*calendar_objects_details', '*PREFIX*calendar_objects', '*PREFIX*calendar_calendars', '*PREFIX*hr_jobmanager'));
      }
      return $data;
   }

   public function _getLastInterview($query) {
      $db = PFactory::getDbo();
      $db->setQuery(PUtil::replaceOCPrefix($query));
      $totalinterview = $db->loadAssoc(); 
      return count($totalinterview)>0 ? $totalinterview : false;
   }

   public function getCompanyIndustryList(){
      $db = PFactory::getDbo();
      $query = 'select id, industry from #__jobs_industry WHERE companyonly=1';
      $db->setQuery($query);    
      return $db->loadAssocList();
   }
}

